This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

source("tianfengRwrappers.R")
载入需要的程辑包:dplyr

载入程辑包:‘dplyr’

The following object is masked from ‘package:matrixStats’:

    count

The following object is masked from ‘package:Biobase’:

    combine

The following objects are masked from ‘package:GenomicRanges’:

    intersect, setdiff, union

The following object is masked from ‘package:GenomeInfoDb’:

    intersect

The following objects are masked from ‘package:IRanges’:

    collapse, desc, intersect, setdiff, slice, union

The following objects are masked from ‘package:S4Vectors’:

    first, intersect, rename, setdiff, setequal, union

The following objects are masked from ‘package:BiocGenerics’:

    combine, intersect, setdiff, union

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union

载入需要的程辑包:reticulate
载入需要的程辑包:tidyr

载入程辑包:‘tidyr’

The following object is masked from ‘package:S4Vectors’:

    expand


载入程辑包:‘MySeuratWrappers’

The following objects are masked from ‘package:Seurat’:

    DimPlot, DoHeatmap, LabelClusters, RidgePlot, VlnPlot


载入程辑包:‘cowplot’

The following object is masked from ‘package:ggpubr’:

    get_legend

载入需要的程辑包:viridisLite

载入程辑包:‘reshape2’

The following object is masked from ‘package:tidyr’:

    smiths

NOTE: Either Arial Narrow or Roboto Condensed fonts are required to use these themes.
      Please use hrbrthemes::import_roboto_condensed() to install Roboto Condensed and
      if Arial Narrow is not on your system, please see https://bit.ly/arialnarrow

Registered S3 method overwritten by 'enrichplot':
  method               from
  fortify.enrichResult DOSE
clusterProfiler v3.14.3  For help: https://guangchuangyu.github.io/software/clusterProfiler

If you use clusterProfiler in published research, please cite:
Guangchuang Yu, Li-Gen Wang, Yanyan Han, Qing-Yu He. clusterProfiler: an R package for comparing biological themes among gene clusters. OMICS: A Journal of Integrative Biology. 2012, 16(5):284-287.

载入程辑包:‘clusterProfiler’

The following object is masked from ‘package:DelayedArray’:

    simplify

Registering fonts with R

载入程辑包:‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:IRanges’:

    slice

The following object is masked from ‘package:S4Vectors’:

    rename

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout


载入程辑包:‘widgetTools’

The following object is masked from ‘package:dplyr’:

    funs


载入程辑包:‘DynDoc’

The following object is masked from ‘package:DelayedArray’:

    path

The following object is masked from ‘package:BiocGenerics’:

    path


载入程辑包:‘DT’

The following object is masked from ‘package:Seurat’:

    JS

========================================
circlize version 0.4.13
CRAN page: https://cran.r-project.org/package=circlize
Github page: https://github.com/jokergoo/circlize
Documentation: https://jokergoo.github.io/circlize_book/book/

If you use it in published research, please cite:
Gu, Z. circlize implements and enhances circular visualization
  in R. Bioinformatics 2014.

This message can be suppressed by:
  suppressPackageStartupMessages(library(circlize))
========================================

载入需要的程辑包:grid
========================================
ComplexHeatmap version 2.2.0
Bioconductor page: http://bioconductor.org/packages/ComplexHeatmap/
Github page: https://github.com/jokergoo/ComplexHeatmap
Documentation: http://jokergoo.github.io/ComplexHeatmap-reference

If you use it in published research, please cite:
Gu, Z. Complex heatmaps reveal patterns and correlations in multidimensional 
  genomic data. Bioinformatics 2016.
========================================


载入程辑包:‘ComplexHeatmap’

The following object is masked from ‘package:plotly’:

    add_heatmap
source("XGBoost_wrapper.R")

载入程辑包:‘xgboost’

The following object is masked from ‘package:plotly’:

    slice

The following object is masked from ‘package:dplyr’:

    slice

The following object is masked from ‘package:IRanges’:

    slice


载入程辑包:‘Matrix’

The following objects are masked from ‘package:tidyr’:

    expand, pack, unpack

The following object is masked from ‘package:S4Vectors’:

    expand

    __  ___________    __  _____________
   /  |/  / ____/ /   / / / / ___/_  __/
  / /|_/ / /   / /   / / / /\__ \ / /   
 / /  / / /___/ /___/ /_/ /___/ // /    
/_/  /_/\____/_____/\____//____//_/    version 5.4.9
Type 'citation("mclust")' for citing this R package in publications.
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
Registered S3 method overwritten by 'cli':
  method     from    
  print.boxx spatstat
─ Attaching packages ──────────────────────────────── tidyverse 1.3.1 ─
✓ tibble  3.1.5     ✓ stringr 1.4.0
✓ readr   2.1.2     ✓ forcats 0.5.1
✓ purrr   0.3.4     
─ Conflicts ───────────────────────────────── tidyverse_conflicts() ─
x dplyr::collapse()   masks IRanges::collapse()
x dplyr::combine()    masks Biobase::combine(), BiocGenerics::combine()
x dplyr::count()      masks matrixStats::count()
x dplyr::desc()       masks IRanges::desc()
x Matrix::expand()    masks tidyr::expand(), S4Vectors::expand()
x plotly::filter()    masks dplyr::filter(), stats::filter()
x dplyr::first()      masks S4Vectors::first()
x widgetTools::funs() masks dplyr::funs()
x dplyr::lag()        masks stats::lag()
x purrr::map()        masks mclust::map()
x Matrix::pack()      masks tidyr::pack()
x ggplot2::Position() masks BiocGenerics::Position(), base::Position()
x purrr::reduce()     masks GenomicRanges::reduce(), IRanges::reduce()
x plotly::rename()    masks dplyr::rename(), S4Vectors::rename()
x purrr::simplify()   masks clusterProfiler::simplify(), DelayedArray::simplify()
x xgboost::slice()    masks plotly::slice(), dplyr::slice(), IRanges::slice()
x Matrix::unpack()    masks tidyr::unpack()

载入程辑包:‘lambda.r’

The following object is masked from ‘package:reticulate’:

    %as%

Creating a generic function for ‘toJSON’ from package ‘jsonlite’ in package ‘googleVis’

harmony

library(harmony)
Idents(ds0) <- "ds0"
Idents(ds1) <- "ds1"
Idents(ds2) <- "ds2"
CAD_merge <- merge(ds0,c(ds1,ds2))
CAD_merge$orig.ident <- Idents(CAD_merge) #存储原始分区

CAD_merge <- CAD_merge %>% 
  PercentageFeatureSet(pattern = "^MT-", col.name = "percent.mt") %>%
  SCTransform(vars.to.regress = "percent.mt", verbose = F) %>% 
  RunPCA()

# saveRDS(CAD_merge, "CAD_merge.rds")

CAD_merge_harmony <- RunHarmony(CAD_merge, "orig.ident", plot_convergence = T, 
                                project.dim = T, assay.use = "SCT")
CAD_merge_harmony@reductions[["pca"]] <- CAD_merge_harmony@reductions[["harmony"]]

CAD_merge_harmony <- CAD_merge_harmony %>% FindNeighbors(dims = 1:20) %>%
  RunUMAP(dims = 1:20) %>% 
  FindClusters(resolution = 0.1)

PCAPlot(CAD_merge_harmony, split.by = "orig.ident")
DimPlot(CAD_merge_harmony, reduction = "harmony", split.by = "orig.ident")

CAD_merge_harmony <- FindClusters(CAD_merge_harmony, resolution = 0.2)
umapplot(CAD_merge_harmony, split.by = "orig.ident")
# saveRDS(CAD_merge_harmony,"CAD_merge_harmony.rds")

亚群标记

selected_features <-intersect(FindVariableFeatures(ds1, nfeatures = 200)@assays[["SCT"]]@var.features,
                              FindVariableFeatures(ds2, nfeatures = 200)@assays[["SCT"]]@var.features) %>%
  intersect(FindVariableFeatures(ds0, nfeatures = 200)@assays[["SCT"]]@var.features)

## ds2作为ref
Idents(ds2) <- ds2$seurat_clusters
bst_model <- XGBoost_train_from_seuobj(ds2)
ds1 <- XGBoost_predict_from_seuobj(ds1, bst_model)
ds1 <- project2ref_celltype(ds1, ds2)
ds0 <- XGBoost_predict_from_seuobj(ds0, bst_model)
ds0 <- project2ref_celltype(ds0, ds2)

ref_sce <- mkref_scmap_from_seuobj(ds2)
ds1 <- query_scmap_from_refsce(ds1, ref_sce)
ds0 <- query_scmap_from_refsce(ds0, ref_sce)

umapplot(ds1, group.by = "ref_celltype")
umapplot(ds0, group.by = "ref_celltype")

umapplot(ds1, group.by = "scmap_idents")
umapplot(ds0, group.by = "scmap_idents")


ds1_scmap <- ds1$scmap_idents
ds1_xgb <- ds1$ref_celltype
ds0_scmap <- ds0$scmap_idents
ds0_xgb <- ds0$ref_celltype
ds2_ref <- ds2$Classification1

ds1_harmony <- subset(CAD_merge_harmony, orig.ident == "ds1")$ds2_celltype
ds0_harmony <- subset(CAD_merge_harmony, orig.ident == "ds0")$ds2_celltype

df <- data.frame(row.names = selected_features)
for(cell_type in c("SMC1","Fibromyocyte","SMC2","Pericyte")){
  df[paste0("ds2ref_",cell_type)] <- data.frame(FetchData(ds2, selected_features, cells = names(ds2_ref[ds2_ref == cell_type]))) %>% colMeans()
  
  df[paste0("ds1scmap",cell_type)] <- data.frame(FetchData(ds1, selected_features, cells = names(ds1_scmap[ds1_scmap == cell_type]))) %>% colMeans() 
  
  df[paste0("ds0scmap",cell_type)] <- data.frame(FetchData(ds0, selected_features, cells = names(ds0_scmap[ds0_scmap == cell_type]))) %>% colMeans()
  
  df[paste0("ds1xgb_",cell_type)] <- data.frame(FetchData(ds1, selected_features, cells = names(ds1_xgb[ds1_xgb == cell_type]))) %>% colMeans()
  
  df[paste0("ds0xgb_",cell_type)] <- data.frame(FetchData(ds0, selected_features, cells = names(ds0_xgb[ds0_xgb == cell_type]))) %>% colMeans()
  
    df[paste0("ds1harmony_",cell_type)] <- data.frame(FetchData(ds1, selected_features, cells = names(ds1_harmony[ds1_harmony == cell_type]))) %>% colMeans()
  
  df[paste0("ds0harmony_",cell_type)] <- data.frame(FetchData(ds0, selected_features, cells = names(ds0_harmony[ds0_harmony == cell_type]))) %>% colMeans()
}

##只考虑SMC2

correlation heatmap

#PCA

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gCgpUcnkgZXhlY3V0aW5nIHRoaXMgY2h1bmsgYnkgY2xpY2tpbmcgdGhlICpSdW4qIGJ1dHRvbiB3aXRoaW4gdGhlIGNodW5rIG9yIGJ5IHBsYWNpbmcgeW91ciBjdXJzb3IgaW5zaWRlIGl0IGFuZCBwcmVzc2luZyAqQ3RybCtTaGlmdCtFbnRlciouIAoKYGBge3J9CnNvdXJjZSgidGlhbmZlbmdSd3JhcHBlcnMuUiIpCnNvdXJjZSgiWEdCb29zdF93cmFwcGVyLlIiKQpgYGAKCiMjIGhhcm1vbnkKYGBge3J9CmxpYnJhcnkoaGFybW9ueSkKSWRlbnRzKGRzMCkgPC0gImRzMCIKSWRlbnRzKGRzMSkgPC0gImRzMSIKSWRlbnRzKGRzMikgPC0gImRzMiIKQ0FEX21lcmdlIDwtIG1lcmdlKGRzMCxjKGRzMSxkczIpKQpDQURfbWVyZ2Ukb3JpZy5pZGVudCA8LSBJZGVudHMoQ0FEX21lcmdlKSAj5a2Y5YKo5Y6f5aeL5YiG5Yy6CgpDQURfbWVyZ2UgPC0gQ0FEX21lcmdlICU+JSAKICBQZXJjZW50YWdlRmVhdHVyZVNldChwYXR0ZXJuID0gIl5NVC0iLCBjb2wubmFtZSA9ICJwZXJjZW50Lm10IikgJT4lCiAgU0NUcmFuc2Zvcm0odmFycy50by5yZWdyZXNzID0gInBlcmNlbnQubXQiLCB2ZXJib3NlID0gRikgJT4lIAogIFJ1blBDQSgpCgojIHNhdmVSRFMoQ0FEX21lcmdlLCAiQ0FEX21lcmdlLnJkcyIpCgpDQURfbWVyZ2VfaGFybW9ueSA8LSBSdW5IYXJtb255KENBRF9tZXJnZSwgIm9yaWcuaWRlbnQiLCBwbG90X2NvbnZlcmdlbmNlID0gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdC5kaW0gPSBULCBhc3NheS51c2UgPSAiU0NUIikKQ0FEX21lcmdlX2hhcm1vbnlAcmVkdWN0aW9uc1tbInBjYSJdXSA8LSBDQURfbWVyZ2VfaGFybW9ueUByZWR1Y3Rpb25zW1siaGFybW9ueSJdXQoKQ0FEX21lcmdlX2hhcm1vbnkgPC0gQ0FEX21lcmdlX2hhcm1vbnkgJT4lIEZpbmROZWlnaGJvcnMoZGltcyA9IDE6MjApICU+JQogIFJ1blVNQVAoZGltcyA9IDE6MjApICU+JSAKICBGaW5kQ2x1c3RlcnMocmVzb2x1dGlvbiA9IDAuMSkKClBDQVBsb3QoQ0FEX21lcmdlX2hhcm1vbnksIHNwbGl0LmJ5ID0gIm9yaWcuaWRlbnQiKQpEaW1QbG90KENBRF9tZXJnZV9oYXJtb255LCByZWR1Y3Rpb24gPSAiaGFybW9ueSIsIHNwbGl0LmJ5ID0gIm9yaWcuaWRlbnQiKQoKQ0FEX21lcmdlX2hhcm1vbnkgPC0gRmluZENsdXN0ZXJzKENBRF9tZXJnZV9oYXJtb255LCByZXNvbHV0aW9uID0gMC4yKQp1bWFwcGxvdChDQURfbWVyZ2VfaGFybW9ueSwgc3BsaXQuYnkgPSAib3JpZy5pZGVudCIpCiMgc2F2ZVJEUyhDQURfbWVyZ2VfaGFybW9ueSwiQ0FEX21lcmdlX2hhcm1vbnkucmRzIikKCgpgYGAKCiMjIOS6mue+pOagh+iusApgYGB7cn0KSWRlbnRzKGRzMikgPC0gZHMyJENsYXNzaWZpY2F0aW9uMQpVTUFQUGxvdChDQURfbWVyZ2VfaGFybW9ueSwgbGFiZWwgPSBULCBjZWxscy5oaWdobGlnaHQgPSBXaGljaENlbGxzKGRzMiwgaWRlbnRzID0gIkZpYnJvYmxhc3QiKSkKIyMgNSAtLSBTTUMyICAwLDIgLS0gU01DMSAgNCw2IC0tIEZCTSAgMyw4IC0tRkIgIDEgLS1wZXJpY3l0ZSAgNyAtLSBtaXhlZCBjZWxscwpsZXZlbHMoSWRlbnRzKENBRF9tZXJnZV9oYXJtb255KSkgPC0gYygiU01DMSIsIlBlcmljeXRlIiwiU01DMSIsIkZpYnJvYmxhc3QiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkZpYnJvbXlvY3l0ZSIsIlNNQzIiLCJGaWJyb215b2N5dGUiLCJNaXhlZCBjZWxscyIsIkZpYnJvYmxhc3QiKQpDQURfbWVyZ2VfaGFybW9ueSRkczJfY2VsbHR5cGUgPC0gSWRlbnRzKENBRF9tZXJnZV9oYXJtb255KQpmKCJMVU0iLENBRF9tZXJnZV9oYXJtb255LHJlZHVjdGlvbiA9ICJ1bWFwIikKYGBgCgoKYGBge3J9CnNlbGVjdGVkX2ZlYXR1cmVzIDwtaW50ZXJzZWN0KEZpbmRWYXJpYWJsZUZlYXR1cmVzKGRzMSwgbmZlYXR1cmVzID0gMjAwKUBhc3NheXNbWyJTQ1QiXV1AdmFyLmZlYXR1cmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGaW5kVmFyaWFibGVGZWF0dXJlcyhkczIsIG5mZWF0dXJlcyA9IDIwMClAYXNzYXlzW1siU0NUIl1dQHZhci5mZWF0dXJlcykgJT4lCiAgaW50ZXJzZWN0KEZpbmRWYXJpYWJsZUZlYXR1cmVzKGRzMCwgbmZlYXR1cmVzID0gMjAwKUBhc3NheXNbWyJTQ1QiXV1AdmFyLmZlYXR1cmVzKQoKIyMgZHMy5L2c5Li6cmVmCklkZW50cyhkczIpIDwtIGRzMiRzZXVyYXRfY2x1c3RlcnMKYnN0X21vZGVsIDwtIFhHQm9vc3RfdHJhaW5fZnJvbV9zZXVvYmooZHMyKQpkczEgPC0gWEdCb29zdF9wcmVkaWN0X2Zyb21fc2V1b2JqKGRzMSwgYnN0X21vZGVsKQpkczEgPC0gcHJvamVjdDJyZWZfY2VsbHR5cGUoZHMxLCBkczIpCmRzMCA8LSBYR0Jvb3N0X3ByZWRpY3RfZnJvbV9zZXVvYmooZHMwLCBic3RfbW9kZWwpCmRzMCA8LSBwcm9qZWN0MnJlZl9jZWxsdHlwZShkczAsIGRzMikKCnJlZl9zY2UgPC0gbWtyZWZfc2NtYXBfZnJvbV9zZXVvYmooZHMyKQpkczEgPC0gcXVlcnlfc2NtYXBfZnJvbV9yZWZzY2UoZHMxLCByZWZfc2NlKQpkczAgPC0gcXVlcnlfc2NtYXBfZnJvbV9yZWZzY2UoZHMwLCByZWZfc2NlKQoKdW1hcHBsb3QoZHMxLCBncm91cC5ieSA9ICJyZWZfY2VsbHR5cGUiKQp1bWFwcGxvdChkczAsIGdyb3VwLmJ5ID0gInJlZl9jZWxsdHlwZSIpCgp1bWFwcGxvdChkczEsIGdyb3VwLmJ5ID0gInNjbWFwX2lkZW50cyIpCnVtYXBwbG90KGRzMCwgZ3JvdXAuYnkgPSAic2NtYXBfaWRlbnRzIikKCgpkczFfc2NtYXAgPC0gZHMxJHNjbWFwX2lkZW50cwpkczFfeGdiIDwtIGRzMSRyZWZfY2VsbHR5cGUKZHMwX3NjbWFwIDwtIGRzMCRzY21hcF9pZGVudHMKZHMwX3hnYiA8LSBkczAkcmVmX2NlbGx0eXBlCmRzMl9yZWYgPC0gZHMyJENsYXNzaWZpY2F0aW9uMQoKZHMxX2hhcm1vbnkgPC0gc3Vic2V0KENBRF9tZXJnZV9oYXJtb255LCBvcmlnLmlkZW50ID09ICJkczEiKSRkczJfY2VsbHR5cGUKZHMwX2hhcm1vbnkgPC0gc3Vic2V0KENBRF9tZXJnZV9oYXJtb255LCBvcmlnLmlkZW50ID09ICJkczAiKSRkczJfY2VsbHR5cGUKCmRmIDwtIGRhdGEuZnJhbWUocm93Lm5hbWVzID0gc2VsZWN0ZWRfZmVhdHVyZXMpCmZvcihjZWxsX3R5cGUgaW4gYygiU01DMSIsIkZpYnJvbXlvY3l0ZSIsIlNNQzIiLCJQZXJpY3l0ZSIpKXsKICBkZltwYXN0ZTAoImRzMnJlZl8iLGNlbGxfdHlwZSldIDwtIGRhdGEuZnJhbWUoRmV0Y2hEYXRhKGRzMiwgc2VsZWN0ZWRfZmVhdHVyZXMsIGNlbGxzID0gbmFtZXMoZHMyX3JlZltkczJfcmVmID09IGNlbGxfdHlwZV0pKSkgJT4lIGNvbE1lYW5zKCkKICAKICBkZltwYXN0ZTAoImRzMXNjbWFwIixjZWxsX3R5cGUpXSA8LSBkYXRhLmZyYW1lKEZldGNoRGF0YShkczEsIHNlbGVjdGVkX2ZlYXR1cmVzLCBjZWxscyA9IG5hbWVzKGRzMV9zY21hcFtkczFfc2NtYXAgPT0gY2VsbF90eXBlXSkpKSAlPiUgY29sTWVhbnMoKSAKICAKICBkZltwYXN0ZTAoImRzMHNjbWFwIixjZWxsX3R5cGUpXSA8LSBkYXRhLmZyYW1lKEZldGNoRGF0YShkczAsIHNlbGVjdGVkX2ZlYXR1cmVzLCBjZWxscyA9IG5hbWVzKGRzMF9zY21hcFtkczBfc2NtYXAgPT0gY2VsbF90eXBlXSkpKSAlPiUgY29sTWVhbnMoKQogIAogIGRmW3Bhc3RlMCgiZHMxeGdiXyIsY2VsbF90eXBlKV0gPC0gZGF0YS5mcmFtZShGZXRjaERhdGEoZHMxLCBzZWxlY3RlZF9mZWF0dXJlcywgY2VsbHMgPSBuYW1lcyhkczFfeGdiW2RzMV94Z2IgPT0gY2VsbF90eXBlXSkpKSAlPiUgY29sTWVhbnMoKQogIAogIGRmW3Bhc3RlMCgiZHMweGdiXyIsY2VsbF90eXBlKV0gPC0gZGF0YS5mcmFtZShGZXRjaERhdGEoZHMwLCBzZWxlY3RlZF9mZWF0dXJlcywgY2VsbHMgPSBuYW1lcyhkczBfeGdiW2RzMF94Z2IgPT0gY2VsbF90eXBlXSkpKSAlPiUgY29sTWVhbnMoKQogIAogICAgZGZbcGFzdGUwKCJkczFoYXJtb255XyIsY2VsbF90eXBlKV0gPC0gZGF0YS5mcmFtZShGZXRjaERhdGEoZHMxLCBzZWxlY3RlZF9mZWF0dXJlcywgY2VsbHMgPSBuYW1lcyhkczFfaGFybW9ueVtkczFfaGFybW9ueSA9PSBjZWxsX3R5cGVdKSkpICU+JSBjb2xNZWFucygpCiAgCiAgZGZbcGFzdGUwKCJkczBoYXJtb255XyIsY2VsbF90eXBlKV0gPC0gZGF0YS5mcmFtZShGZXRjaERhdGEoZHMwLCBzZWxlY3RlZF9mZWF0dXJlcywgY2VsbHMgPSBuYW1lcyhkczBfaGFybW9ueVtkczBfaGFybW9ueSA9PSBjZWxsX3R5cGVdKSkpICU+JSBjb2xNZWFucygpCn0KYGBgCgojI+WPquiAg+iZkVNNQzIKYGBge3J9CnNlbGVjdGVkX2ZlYXR1cmVzIDwtIHJlYWQudGFibGUoIlNNQzIiKSAjU01DMiBtYXJrZXJzIGluIGRzMgpzZWxlY3RlZF9mZWF0dXJlcyA8LSBhcy5jaGFyYWN0ZXIoc2VsZWN0ZWRfZmVhdHVyZXMkVjEpCgoKdGVtcCA8LSBnZXRfZGF0YV90YWJsZShkczAsIGhpZ2h2YXIgPSBULCB0eXBlID0gImRhdGEiKQpkczBfZGF0YSA8LSBtYXRyaXgoZGF0YSA9IDAsIG5yb3cgPSBsZW5ndGgoc2VsZWN0ZWRfZmVhdHVyZXMpLCBuY29sID0gbGVuZ3RoKGNvbG5hbWVzKHRlbXApKSwgCiAgICAgICAgICAgICAgICAgICBieXJvdyA9IEZBTFNFLCBkaW1uYW1lcyA9IGxpc3Qoc2VsZWN0ZWRfZmVhdHVyZXMsY29sbmFtZXModGVtcCkpKQppbnRlcnNlY3RfZmVhdHVyZXMgPC0gaW50ZXJzZWN0KHNlbGVjdGVkX2ZlYXR1cmVzLCByb3duYW1lcyh0ZW1wKSkKZHMwX2RhdGFbaW50ZXJzZWN0X2ZlYXR1cmVzLF0gPC0gdGVtcFtpbnRlcnNlY3RfZmVhdHVyZXMsXQpybSh0ZW1wKQoKZGYgPC0gZGF0YS5mcmFtZShyb3cubmFtZXMgPSBzZWxlY3RlZF9mZWF0dXJlcykKZm9yKGNlbGxfdHlwZSBpbiBjKCJTTUMyIikpewogIGRmW3Bhc3RlMCgiZHMycmVmXyIsY2VsbF90eXBlKV0gPC0gZGF0YS5mcmFtZShGZXRjaERhdGEoZHMyLCBzZWxlY3RlZF9mZWF0dXJlcywgY2VsbHMgPSBuYW1lcyhkczJfcmVmW2RzMl9yZWYgPT0gY2VsbF90eXBlXSkpKSAlPiUgY29sTWVhbnMoKQogIAogIGRmW3Bhc3RlMCgiZHMxc2NtYXBfIixjZWxsX3R5cGUpXSA8LSBkYXRhLmZyYW1lKEZldGNoRGF0YShkczEsIHNlbGVjdGVkX2ZlYXR1cmVzLCBjZWxscyA9IG5hbWVzKGRzMV9zY21hcFtkczFfc2NtYXAgPT0gY2VsbF90eXBlXSkpKSAlPiUgY29sTWVhbnMoKSAKICAKICBkZltwYXN0ZTAoImRzMHNjbWFwXyIsY2VsbF90eXBlKV0gPC0gdChkczBfZGF0YVssbmFtZXMoZHMwX3NjbWFwW2RzMF9zY21hcCA9PSBjZWxsX3R5cGVdKV0pICU+JSBjb2xNZWFucygpCiAgCiAgZGZbcGFzdGUwKCJkczF4Z2JfIixjZWxsX3R5cGUpXSA8LSBkYXRhLmZyYW1lKEZldGNoRGF0YShkczEsIHNlbGVjdGVkX2ZlYXR1cmVzLCBjZWxscyA9IG5hbWVzKGRzMV94Z2JbZHMxX3hnYiA9PSBjZWxsX3R5cGVdKSkpICU+JSBjb2xNZWFucygpCiAgCiAgZGZbcGFzdGUwKCJkczB4Z2JfIixjZWxsX3R5cGUpXSA8LSAgdChkczBfZGF0YVssbmFtZXMoZHMwX3hnYltkczBfeGdiID09IGNlbGxfdHlwZV0pXSkgICU+JSBjb2xNZWFucygpCiAgCiAgZGZbcGFzdGUwKCJkczFoYXJtb255XyIsY2VsbF90eXBlKV0gPC0gZGF0YS5mcmFtZShGZXRjaERhdGEoZHMxLCBzZWxlY3RlZF9mZWF0dXJlcywgY2VsbHMgPSBuYW1lcyhkczFfaGFybW9ueVtkczFfaGFybW9ueSA9PSBjZWxsX3R5cGVdKSkpICU+JSBjb2xNZWFucygpCiAgCiAgZGZbcGFzdGUwKCJkczBoYXJtb255XyIsY2VsbF90eXBlKV0gPC0gdChkczBfZGF0YVssbmFtZXMoZHMwX2hhcm1vbnlbZHMwX2hhcm1vbnkgPT0gY2VsbF90eXBlXSldKSAlPiUgY29sTWVhbnMoKQogIAogIGRmW3Bhc3RlMCgiZHMxc3ZtXyIsY2VsbF90eXBlKV0gPC0gZGF0YS5mcmFtZShGZXRjaERhdGEoZHMxLCBzZWxlY3RlZF9mZWF0dXJlcywgY2VsbHMgPSBuYW1lcyhkczFfc3ZtW2RzMV9zdm0gPT0gY2VsbF90eXBlXSkpKSAlPiUgY29sTWVhbnMoKQogIAogIGRmW3Bhc3RlMCgiZHMwc3ZtXyIsY2VsbF90eXBlKV0gPC0gdChkczBfZGF0YVssbmFtZXMoZHMwX3N2bVtkczBfc3ZtID09IGNlbGxfdHlwZV0pXSkgJT4lIGNvbE1lYW5zKCkKfQpkZiA8LSBkZlssIWlzLm5hKGRmWzEsXSldICPliKDpmaROQeWIlwpgYGAKCiMgY29ycmVsYXRpb24gaGVhdG1hcApgYGB7ciBmaWcud2lkdGg9NiwgZmlnLmhlaWdodD02fQpjb3JyIDwtIGNvcihkZixtZXRob2QgPSAic3BlYXJtYW4iKQpwaGVhdG1hcDo6cGhlYXRtYXAoY29ycixicmVha3MgPSB1bmlxdWUoYyhzZXEoMC42LCAxLCBsZW5ndGggPSAxMDApKSksCiAgICAgICAgY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKGMoIiMxRTkwRkYiLCAid2hpdGUiLCAiI2ZmMjEyMSIpKSgxMDApLAogICAgICAgIGJvcmRlcl9jb2xvciA9IE5BLCBjbHVzdGVyX3Jvd3MgPSBGLCBjbHVzdGVyX2NvbHMgPSBGLAogICAgICAgIG1haW4gPSAiY29yciIsIGFuZ2xlX2NvbCA9IDQ1LCBzaG93X3Jvd25hbWVzID0gVCwgbmFfY29sID0gImdyZXkiKQoKIyBjb3JyW2lzLm5hKGNvcnIpXSA8LSAwICPogZrnsbvml7bkuI3og73mnIlOQQpwaGVhdG1hcDo6cGhlYXRtYXAoY29ycixicmVha3MgPSB1bmlxdWUoYyhzZXEoMC40LCAxLCBsZW5ndGggPSAxMDApKSksCiAgICAgICAgY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKGMoIiMxRTkwRkYiLCAid2hpdGUiLCAiI2ZmMjEyMSIpKSgxMDApLAogICAgICAgIGJvcmRlcl9jb2xvciA9IE5BLCBjbHVzdGVyX3Jvd3MgPSBULCBjbHVzdGVyX2NvbHMgPSBULCBmb250c2l6ZSA9IDE1LAogICAgICAgIG1haW4gPSAiU01DMiIsIGFuZ2xlX2NvbCA9IDQ1LCBzaG93X3Jvd25hbWVzID0gVCkgCgpsaWJyYXJ5KGdnY29yKQpxdWlja2NvcihkZiwgdHlwZSA9ICJ1cHBlciIpICsgZ2VvbV9jaXJjbGUyKCkKYGBgCgojUENBCmBgYHtyfQojIHJlcyA8LSBkYXRhLmZyYW1lKHJvdy5uYW1lcyA9IGMoIkEiLCJCIiwiQyIpKQpvcHRpb25zKHN0cmluZ3NBc0ZhY3RvcnMgPSBUKQpybSh0ZW1wX3Jlc3VsdCkKZm9yKGNlbGxfdHlwZSBpbiBjKCJTTUMxIiwiRmlicm9teW9jeXRlIiwiUGVyaWN5dGUiLCJTTUMyIikpewogIAogIGRmMSA8LSBkYXRhLmZyYW1lKEZldGNoRGF0YShkczIsIHNlbGVjdGVkX2ZlYXR1cmVzLCBjZWxscyA9IG5hbWVzKGRzMl9yZWZbZHMyX3JlZiA9PSBjZWxsX3R5cGVdKSksCiAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImRzMnJlZiIsIGNlbGx0eXBlID0gY2VsbF90eXBlLCBsYWJlbCA9IHBhc3RlMChjZWxsX3R5cGUsICJfZHMycmVmIikpCiAgCiAgZGYyIDwtIGRhdGEuZnJhbWUoRmV0Y2hEYXRhKGRzMSwgc2VsZWN0ZWRfZmVhdHVyZXMsIGNlbGxzID0gbmFtZXMoZHMxX3NjbWFwW2RzMV9zY21hcCA9PSBjZWxsX3R5cGVdKSksCiAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImRzMXNjbWFwIiwgY2VsbHR5cGUgPSBjZWxsX3R5cGUsIGxhYmVsID0gcGFzdGUwKGNlbGxfdHlwZSwgIl9kczFzY21hcCIpKSAgIAogIAogIGRmMyA8LSBkYXRhLmZyYW1lKEZldGNoRGF0YShkczAsIHNlbGVjdGVkX2ZlYXR1cmVzLCBjZWxscyA9IG5hbWVzKGRzMF9zY21hcFtkczBfc2NtYXAgPT0gY2VsbF90eXBlXSkpLAogICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJkczBzY21hcCIsIGNlbGx0eXBlID0gY2VsbF90eXBlLCBsYWJlbCA9IHBhc3RlMChjZWxsX3R5cGUsICJfZHMwc2NtYXAiKSkgIAogIAogIGRmNCA8LSBkYXRhLmZyYW1lKEZldGNoRGF0YShkczEsIHNlbGVjdGVkX2ZlYXR1cmVzLCBjZWxscyA9IG5hbWVzKGRzMV94Z2JbZHMxX3hnYiA9PSBjZWxsX3R5cGVdKSksCiAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImRzMXhnYiIsIGNlbGx0eXBlID0gY2VsbF90eXBlLCBsYWJlbCA9IHBhc3RlMChjZWxsX3R5cGUsICJfZHMxeGdiIikpICAKICAKICBpZihjZWxsX3R5cGUgIT0gIlNNQzIiKXsKICBkZjUgPC0gZGF0YS5mcmFtZShGZXRjaERhdGEoZHMwLCBzZWxlY3RlZF9mZWF0dXJlcywgY2VsbHMgPSBuYW1lcyhkczBfeGdiW2RzMF94Z2IgPT0gY2VsbF90eXBlXSkpLAogICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJkczB4Z2IiLCBjZWxsdHlwZSA9IGNlbGxfdHlwZSwgbGFiZWwgPSBwYXN0ZTAoY2VsbF90eXBlLCAiX2RzMHhnYiIpKX0KICAKICBkZjYgPC0gZGF0YS5mcmFtZShGZXRjaERhdGEoZHMxLCBzZWxlY3RlZF9mZWF0dXJlcywgY2VsbHMgPSBuYW1lcyhkczFfaGFybW9ueVtkczFfaGFybW9ueSA9PSBjZWxsX3R5cGVdKSksCiAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImRzMWhhcm1vbnkiLCBjZWxsdHlwZSA9IGNlbGxfdHlwZSwgbGFiZWwgPSBwYXN0ZTAoY2VsbF90eXBlLCAiX2RzMWhhcm1vbnkiKSkKICAKICBkZjcgPC0gZGF0YS5mcmFtZShGZXRjaERhdGEoZHMwLCBzZWxlY3RlZF9mZWF0dXJlcywgY2VsbHMgPSBuYW1lcyhkczBfaGFybW9ueVtkczBfaGFybW9ueSA9PSBjZWxsX3R5cGVdKSksCiAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImRzMGhhcm1vbnkiLCBjZWxsdHlwZSA9IGNlbGxfdHlwZSwgbGFiZWwgPSBwYXN0ZTAoY2VsbF90eXBlLCAiX2RzMGhhcm1vbnkiKSkgIAogIGlmKGV4aXN0cygidGVtcF9yZXN1bHQiKSl7CiAgdGVtcF9yZXN1bHQgPC0gcmJpbmQodGVtcF9yZXN1bHQsZGYxLGRmMixkZjMsZGY0LGRmNSxkZjYsZGY3KQogIH1lbHNlewogICAgdGVtcF9yZXN1bHQgPC0gcmJpbmQoZGYxLGRmMixkZjMsZGY0LGRmNSxkZjYsZGY3KQogIH0KICAKCiAgIyAKICAjIHZfZHMwIDwtIGRkW2RkJHR5cGUgPT0gImRzMCIsYygxOjUpXSAlPiUgY29sTWVhbnMoKSAlPiUgYXMubWF0cml4KCkKICAjIHZfZHMxIDwtIGRkW2RkJHR5cGUgPT0gImRzMSIsYygxOjUpXSAlPiUgY29sTWVhbnMoKSAlPiUgYXMubWF0cml4KCkKICAjIHZfZHMyIDwtIGRkW2RkJHR5cGUgPT0gImRzMiIsYygxOjUpXSAlPiUgY29sTWVhbnMoKSAlPiUgYXMubWF0cml4KCkKICAjIHYgPC0gYyhub3JtKHZfZHMwLXZfZHMyKSxub3JtKHZfZHMxLXZfZHMyKSxub3JtKHZfZHMwLXZfZHMxKSkKICAjIHJlc1tjZWxsX3R5cGVdIDwtIHYKfQojIHJlcwoKUENBcmVzIDwtIHRlbXBfcmVzdWx0WyxjKC1uY29sKHRlbXBfcmVzdWx0KSwtbmNvbCh0ZW1wX3Jlc3VsdCkrMSwtbmNvbCh0ZW1wX3Jlc3VsdCkrMildICU+JQogIEZhY3RvTWluZVI6OlBDQShuY3AgPSA1LCBncmFwaCA9IEYpCmRkIDwtIGNiaW5kKFBDQXJlc1tbImluZCJdXVtbImNvb3JkIl1dLCAKICAgICAgICAgICAgZGF0YS5mcmFtZShtZXRob2QgPSB0ZW1wX3Jlc3VsdFssIm1ldGhvZCJdLCBjZWxsdHlwZSA9IHRlbXBfcmVzdWx0WywiY2VsbHR5cGUiXSksIAogICAgICAgICAgICBsYWJlbCA9IHRlbXBfcmVzdWx0WywibGFiZWwiXSkKZ2dwbG90KGRkKSArIGdlb21fcG9pbnQoYWVzKHggPSBEaW0uMSwgeSA9IERpbS4yLCBjb2xvciA9IG1ldGhvZCwgc2hhcGUgPSBjZWxsdHlwZSksIGFscGhhID0gMC4yLCBzaXplID0gMikgKyB0aGVtZV9jbGFzc2ljKCkKCm1lYW5fUENBIDwtIGxhcHBseShsZXZlbHMoZGQkbGFiZWwpLCBmdW5jdGlvbih0eXBlLCBkZCl7ZGRbZGQkbGFiZWwgPT0gdHlwZSxjKDE6NSldICU+JSBjb2xNZWFucygpfSxkZCkgJT4lIAogICAgYXMuZGF0YS5mcmFtZShjb2wubmFtZXMgPSBsZXZlbHMoZGQkbGFiZWwpKSAlPiUgdCgpICU+JSBhcy5kYXRhLmZyYW1lKCkKCm1lYW5fUENBJGxhYmVsIDwtIHJvd25hbWVzKG1lYW5fUENBKQp0ZW1wIDwtIHQoYXMuZGF0YS5mcmFtZShzdHJzcGxpdChtZWFuX1BDQSRsYWJlbCwiXyIpKSkKY29sbmFtZXModGVtcCkgPC0gYygiY2VsbHR5cGUiLCJtZXRob2QiKQptZWFuX1BDQSA8LSBjYmluZChtZWFuX1BDQSwgdGVtcCkKCnAgPC0gZ2dwbG90KGRhdGEgPSBtZWFuX1BDQSkgKyAKICBnZW9tX3BvaW50KGFlcyh4ID0gRGltLjEsIHkgPSBEaW0uMiwgc2hhcGUgPSBjZWxsdHlwZSwgY29sb3IgPSBtZXRob2QpLCBzaXplID0gNCkgKyAKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICJibGFjayIsIHNpemUgPSAxNiksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vci55ID0gZWxlbWVudF9ibGFuaygpLHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLAogICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQ9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsY29sb3I9ImJsYWNrIixoanVzdCA9IDAuNSksCiAgICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNixjb2xvciA9ImJsYWNrIiksIAogICAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9IDE2LGNvbG9yID0gImJsYWNrIikpICsgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IGMoMTU6MTgpKSArIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvcnNfbGlzdCkKcApnZ3NhdmUoIlBDQV9wbG90LnN2ZyIscGxvdCA9IHAsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNCwgZGV2aWNlID0gc3ZnKQojIGdnc2F2ZSgiUENBX3Bsb3QucG5nIixwbG90ID0gcCwgd2lkdGggPSA2LCBoZWlnaHQgPSA0LCBkZXZpY2UgPSBwbmcpCgpzYXZlLmltYWdlKCkKYGBgCgpgYGB7cn0KCmBgYAoKCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDdHJsK0FsdCtJKi4KCldoZW4geW91IHNhdmUgdGhlIG5vdGVib29rLCBhbiBIVE1MIGZpbGUgY29udGFpbmluZyB0aGUgY29kZSBhbmQgb3V0cHV0IHdpbGwgYmUgc2F2ZWQgYWxvbmdzaWRlIGl0IChjbGljayB0aGUgKlByZXZpZXcqIGJ1dHRvbiBvciBwcmVzcyAqQ3RybCtTaGlmdCtLKiB0byBwcmV2aWV3IHRoZSBIVE1MIGZpbGUpLgoKVGhlIHByZXZpZXcgc2hvd3MgeW91IGEgcmVuZGVyZWQgSFRNTCBjb3B5IG9mIHRoZSBjb250ZW50cyBvZiB0aGUgZWRpdG9yLiBDb25zZXF1ZW50bHksIHVubGlrZSAqS25pdCosICpQcmV2aWV3KiBkb2VzIG5vdCBydW4gYW55IFIgY29kZSBjaHVua3MuIEluc3RlYWQsIHRoZSBvdXRwdXQgb2YgdGhlIGNodW5rIHdoZW4gaXQgd2FzIGxhc3QgcnVuIGluIHRoZSBlZGl0b3IgaXMgZGlzcGxheWVkLgo=